package com.beetlestech.nfe.main.biz.com.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import com.beetlestech.nfe.fw.core.biz.AbstractMasterCache;
import com.beetlestech.nfe.fw.core.util.CollectionUtil;
import com.beetlestech.nfe.fw.core.util.StringUtil;
import com.beetlestech.nfe.main.biz.com.HbMasterCache;
import com.beetlestech.nfe.main.biz.com.dto.CodeWithValueDTO;
import com.beetlestech.nfe.main.biz.constant.MasterCacheConstant;
import com.beetlestech.nfe.main.db.base.StatementDTO;
import com.beetlestech.nfe.main.db.base.StatementUtil;
import com.beetlestech.nfe.main.db.tbl.TcomblcmDTO;

/**
 * マスターキャッシュ Bizロジックの実装ロジック
 *
 * 変更履歴
 * REV.         変更日付           変更者              変更内容
 * -------      ---------------    ----------------    ------------------
 * 1.0          2013/04/17         GD Ma Ji Ao         新規作成
 * 1.1			2013/06/26		   GD Ma Ji Ao		   変更0009対応
 * 1.2          2014/04/18         GD Yang De Chuan    変更0213対応
 *
 */
public class HbMasterCacheImpl extends AbstractMasterCache implements HbMasterCache, MasterCacheConstant {

	/** ビジネスロジック設定マスターのマップ
	 */
	private static HashMap<String, Object> tcomblcmMap = null;

	/* (non-Javadoc)
	 * @see com.beetlestech.nfe.main.biz.com.HbMasterCache#getMasterData(com.beetlestech.nfe.main.biz.com.HbMasterCache.MASTER_NAME, java.lang.Object[])
	 */
	@SuppressWarnings("unchecked")
	@Override
	public <E> E getMasterData(
			MASTER_NAME name,
			Object... parameters) {

		E result = null;

		switch (name) {
		//ビジネスロジック設定マスターの場合
		case TCOMBLCM:
			result = (E) getTcomblcmData(parameters);
			break;
		default:
			break;
		}
		return result;
	}

	/* (non-Javadoc)
	 * @see com.beetlestech.nfe.main.biz.com.HbMasterCache#refreshMasterData(com.beetlestech.nfe.main.biz.com.HbMasterCache.MASTER_NAME)
	 */
	@Override
	public void refreshMasterData(
			MASTER_NAME name) {

		switch (name) {
		case TCOMBLCM:
			refreshTcomblcmData();
			break;
		default:
			break;
		}

		return;
	}

	/* (non-Javadoc)
	 * @see com.beetlestech.nfe.main.biz.com.HbMasterCache#loadMasterData(com.beetlestech.nfe.main.biz.com.HbMasterCache.MASTER_NAME)
	 */
	@Override
	public void loadMasterData(
			MASTER_NAME name) {
		switch (name) {
		case TCOMBLCM:
			loadTcomblcmData();
			break;
		default:
			break;
		}
		return;
	}
	
	public CodeWithValueDTO[] getMasterList(
			MasterCacheConstant.MASTER_NAME name){
		CodeWithValueDTO[] result = null;

		switch (name) {
		//ビジネスロジック設定マスターの場合
		case TCOMBLCM:
			result = getTcomblcmList();
			break;
		default:
			break;
		}
		return result;
	}

	/**
	 * 次のパラメーターを取得
	 *
	 * @param parameters	パラメーター
	 *
	 * @return	Object[]	次のパラメーター
	 */
	private Object[] getNextParameters(
			Object[] parameters) {
		Object[] nextParameters = null;
		if (parameters != null && parameters.length >= 2) {
			nextParameters = new Object[parameters.length - 1];
			for (int i = 1; i < parameters.length; i++) {
				nextParameters[i - 1] = parameters[i];
			}
		}
		return nextParameters;
	}

	/**
	 * ビジネスロジック設定マスターをロードする
	 *
	 */
	private void loadTcomblcmData() {
		StatementDTO statementDTO = new StatementDTO();
		StatementUtil.addOrderBy(statementDTO, TcomblcmDTO.COLUMN_APPL_ID, null);
		StatementUtil.addOrderBy(statementDTO, TcomblcmDTO.COLUMN_FUNCTION_ID, null);
		StatementUtil.addOrderBy(statementDTO, TcomblcmDTO.COLUMN_ITEM_ID, null);
		TcomblcmDTO tcomblcmDTO = new TcomblcmDTO();
		tcomblcmDTO.set_orderByCondition(statementDTO.getSQLOrderByStatement());
		//ビジネスロジック設定マスター情報を取得
		List<TcomblcmDTO> resultDTOs = queryDAO.queryForObjectList(TcomblcmDTO.EQUAL_SEARCH, tcomblcmDTO);
		if (CollectionUtil.isNotEmpty(resultDTOs)) {
			HashMap<String, Object> resultMap = new HashMap<String, Object>();
			HashMap<String, Object> functionIDMap = null;
			HashMap<String, TcomblcmDTO> itemIDMap = null;
			String applID = null;
			String functionID = null;
			for (TcomblcmDTO resultDTO : resultDTOs) {
				if (!resultDTO.getApplId().equals(applID)) {
					applID = resultDTO.getApplId();
					functionIDMap = new HashMap<String, Object>();
					functionID = resultDTO.getFunctionId();
					itemIDMap = new HashMap<String, TcomblcmDTO>();
					//アプリケーションIDをキーとしてマップにレコードをセットする
					resultMap.put(StringUtil.trimRight(resultDTO.getApplId()), functionIDMap);
					//機能IDをキーとしてマップにレコードをセットする
					functionIDMap.put(StringUtil.trimRight(resultDTO.getFunctionId()), itemIDMap);
					//項目IDをキーとしてマップにレコードをセットする
					itemIDMap.put(StringUtil.trimRight(resultDTO.getItemId()), resultDTO);
					continue;
				}

				if (resultDTO.getApplId().equals(applID) && !resultDTO.getFunctionId().equals(functionID)) {
					functionID = resultDTO.getFunctionId();
					itemIDMap = new HashMap<String, TcomblcmDTO>();
					//機能IDをキーとしてマップにレコードをセットする
					functionIDMap.put(StringUtil.trimRight(resultDTO.getFunctionId()), itemIDMap);
					//項目IDをキーとしてマップにレコードをセットする
					itemIDMap.put(StringUtil.trimRight(resultDTO.getItemId()), resultDTO);
					continue;
				}

				//項目IDをキーとしてマップにレコードをセットする
				itemIDMap.put(StringUtil.trimRight(resultDTO.getItemId()), resultDTO);
			}
			tcomblcmMap = resultMap;
		}
	}

	/**
	 * ビジネスロジック設定マスターを取得する
	 *
	 * @param parameters パラメーター
	 * @return キャッシュデータ
	 */
	private List<TcomblcmDTO> getTcomblcmData(
			Object... parameters) {

		List<TcomblcmDTO> resultDTOs = null;
		if (parameters != null) {
			//パラメーターでレコードを取得
			resultDTOs = getAllTcomblcmInfo(parameters);
		} else {
			//全件取得
			resultDTOs = getAllTcomblcmInfo();
		}

		return resultDTOs;
	}
	
	/**
	 * 
	 *
	 * @return 
	 */
	private CodeWithValueDTO[] getTcomblcmList() {

		CodeWithValueDTO[] codeWithValueDTOs = null;

		if (tcomblcmMap == null || tcomblcmMap.isEmpty()) {
			loadTcomblcmData();
		}
		
		codeWithValueDTOs = new CodeWithValueDTO[tcomblcmMap.entrySet().size()];
		int i = 0;
		
		for(Map.Entry<String, Object> entry: tcomblcmMap.entrySet()) {
			CodeWithValueDTO codeWithValueDTO = new CodeWithValueDTO();
			codeWithValueDTO.setCode(entry.getKey());
			codeWithValueDTO.setValue(entry.getKey());
			codeWithValueDTOs[i] = codeWithValueDTO;
			i++;
		}

		return codeWithValueDTOs;
	}

	/**
	 * ビジネスロジック設定マスターを再作成する
	 *
	 */
	private void refreshTcomblcmData() {
		if (tcomblcmMap != null && !tcomblcmMap.isEmpty()) {
			tcomblcmMap.clear();
			loadTcomblcmData();
		} else {
			loadTcomblcmData();
		}

	}

	/**
	 * すべてのビジネスロジック設定マスター情報を取得
	 *
	 * @param parameters	パラメーター
	 *
	 * @return	List<TcomblcmDTO>	ビジネスロジック設定マスター情報
	 */
	@SuppressWarnings("unchecked")
	private List<TcomblcmDTO> getAllTcomblcmInfo(
			Object... parameters) {
		List<TcomblcmDTO> tcomblcmDTOs = null;

		if (tcomblcmMap == null || tcomblcmMap.isEmpty()) {
			loadTcomblcmData();
		}

		if (tcomblcmMap != null && !tcomblcmMap.isEmpty()) {
			tcomblcmDTOs = new ArrayList<TcomblcmDTO>();
			if (parameters != null && parameters.length > 1) {

				List<TcomblcmDTO> resultDTOs = getTcomblcmInfoByApplicationID((HashMap<String, Object>) tcomblcmMap.get(parameters[0]),
						getNextParameters(parameters));
				if (CollectionUtil.isNotEmpty(resultDTOs)) {
					//アプリケーションIDでレコードを取得
					tcomblcmDTOs.addAll(resultDTOs);
				}
			} else {
				Iterator<Map.Entry<String, Object>> resultIter = tcomblcmMap.entrySet().iterator();
				while (resultIter.hasNext()) {
					Map.Entry<String, Object> resultMap = resultIter.next();
					tcomblcmDTOs.addAll(getTcomblcmInfoByApplicationID((HashMap<String, Object>) resultMap.getValue(), null));
				}
			}
		}

		return tcomblcmDTOs;
	}

	/**
	 * アプリケーションIDで共通項目マスター情報を取得
	 *
	 * @param functionIDMap 	アプリケーションIDのマップ
	 * @param parameters	パラメーター
	 *
	 * @return	List<TcomblcmDTO>	共通項目マスター情報
	 */
	@SuppressWarnings("unchecked")
	private List<TcomblcmDTO> getTcomblcmInfoByApplicationID(
			HashMap<String, Object> functionIDMap,
			Object[] parameters) {
		List<TcomblcmDTO> tcomblcmDTOs = null;
		if (functionIDMap != null && !functionIDMap.isEmpty()) {
			tcomblcmDTOs = new ArrayList<TcomblcmDTO>();
			if (parameters != null && parameters.length > 1) {

				List<TcomblcmDTO> resultDTOs = getTcomblcmDTOInfoByFunctionID((HashMap<String, TcomblcmDTO>) functionIDMap.get(parameters[0]),
						getNextParameters(parameters));
				if (CollectionUtil.isNotEmpty(resultDTOs)) {
					//機能IDでレコードを取得
					tcomblcmDTOs.addAll(resultDTOs);
				}
			} else {
				Iterator<Map.Entry<String, Object>> comKey1Iter = functionIDMap.entrySet().iterator();
				while (comKey1Iter.hasNext()) {
					Map.Entry<String, Object> key2Map = comKey1Iter.next();
					tcomblcmDTOs.addAll(getTcomblcmDTOInfoByFunctionID((HashMap<String, TcomblcmDTO>) key2Map.getValue(), null));
				}
			}

		}
		return tcomblcmDTOs;
	}

	/**
	 * 機能IDで共通項目マスター情報を取得
	 *
	 * @param itemIDMap	 機能IDのマップ
	 * @param parameters	パラメーター
	 *
	 * @return	List<TcomblcmDTO>	共通項目マスター情報
	 */
	private List<TcomblcmDTO> getTcomblcmDTOInfoByFunctionID(
			HashMap<String, TcomblcmDTO> itemIDMap,
			Object[] parameters) {
		List<TcomblcmDTO> tcomblcmDTOs = null;
		if (itemIDMap != null && !itemIDMap.isEmpty()) {
			tcomblcmDTOs = new ArrayList<TcomblcmDTO>();
			if (parameters != null && parameters.length == 1) {

				TcomblcmDTO resultDTO = itemIDMap.get(parameters[0]);
				if (resultDTO != null) {
					//項目IDでレコードを取得
					tcomblcmDTOs.add(resultDTO);
				}
			} else {
				Iterator<Map.Entry<String, TcomblcmDTO>> dtoIter = itemIDMap.entrySet().iterator();
				while (dtoIter.hasNext()) {
					Map.Entry<String, TcomblcmDTO> key3Map = dtoIter.next();
					TcomblcmDTO resultDTO = key3Map.getValue();
					tcomblcmDTOs.add(resultDTO);
				}
			}

		}
		return tcomblcmDTOs;
	}

}
